﻿// ----------------------------------------------------------------------------
// debugconsole.cpp
// ----------------------------------------------------------------------------
#include <fw/base/core/macros.h>
#include <fw/base/core/debugconsole.h>
#ifdef NDEBUG
#error hoge
#endif

#include <cstdio>
#include <cassert>
#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

namespace fw
{
    namespace
    {
        // デフォルトのデバッグ文字列出力先
        int DefaultPuts( const char* string )
        {
#if defined(_WIN32) || defined(_WIN64)
#if defined(NDEBUG)
            puts( string );
#endif
            OutputDebugStringA( string );
            return static_cast<int>(strlen( string ));
#else
            return puts( string );
#endif
        }
        
        // デフォルトのデバッグ文字列出力先(wide文字列) 
        int DefaultPutsW( const wchar_t* string )
        {
#if defined(_WIN32) || defined(_WIN64)
#if defined(NDEBUG)
            wprintf( string );
#endif
            OutputDebugStringW( string );
            return static_cast<int>(wcslen( string ));
#else
            return wprintf( string );
#endif
        }
        
        static OutputStringCallback  g_callback  = DefaultPuts;
        static OutputStringCallbackW g_callbackw = DefaultPutsW;
        
        static const int kInternalStringLength = 1024;
        
    } // unnamed namespace 
    
#if defined(_MSC_VER)
#define INTERNAL_VSPRINTF(b,s,f,a)		_vsnprintf_s(b,s,_TRUNCATE,f,a)
#define INTERNAL_VSWPRINTF(b,s,f,a)		_vsnwprintf_s(b,s,_TRUNCATE,f,a)
#else
#define INTERNAL_VSPRINTF 				vsnprintf
#define INTERNAL_VSWPRINTF 				vswprintf
#endif
    
    void SetOutputStringCallback( OutputStringCallback callback )
    {
        assert(callback);
        g_callback = callback;
    }
    
    void SetOutputStringCallbackW( OutputStringCallbackW callback )
    {
        assert(callback);
        g_callbackw = callback;
    }
    int fw_printf(const char* format, ...)
    {
        va_list ap;
        char buffer[kInternalStringLength];
        
        va_start( ap, format );
        INTERNAL_VSPRINTF( buffer, kInternalStringLength-1, format, ap );
        va_end( ap );
        
        return g_callback( buffer );
    }
    
    int fw_wprintf(const wchar_t* format, ...)
    {
        va_list ap;
        wchar_t buffer[kInternalStringLength];
        
        va_start( ap, format );
        INTERNAL_VSWPRINTF( buffer, kInternalStringLength-1, format, ap );
        va_end( ap );
        
        return g_callbackw( buffer );
    }
    
    int fw_vprintf(const char* format, va_list list)
    {
        char buffer[kInternalStringLength];
        
        INTERNAL_VSPRINTF( buffer, kInternalStringLength-1, format, list );
        
        return g_callback( buffer );
    }
    
    int fw_vwprintf(const wchar_t* format, va_list list)
    {
        wchar_t buffer[kInternalStringLength];
        
        INTERNAL_VSWPRINTF( buffer, kInternalStringLength-1, format, list );
        
        return g_callbackw( buffer );
    }

} // namespace fw



